package com.iflyings.android.util

import java.io.ByteArrayOutputStream
import java.io.DataOutputStream
import java.io.IOException
import java.io.InputStream

object ShellUtils {
    private val LINE_SEP = System.getProperty("line.separator")

    fun execCmd(commands: Array<String>, isRooted: Boolean,
                onOutStream: (InputStream) -> Unit,
                onErrorStream: (InputStream) -> Unit) {
        if (commands.isEmpty()) {
            throw IllegalArgumentException("command is empty")
        }
        var process: Process? = null
        try {
            process = Runtime.getRuntime().exec(if (isRooted) "su" else "sh")
            DataOutputStream(process.outputStream).use {
                for (command in commands) {
                    it.writeBytes(command+LINE_SEP)
                    it.flush()
                }
                it.writeBytes("exit$LINE_SEP")
                it.flush()
            }
            onErrorStream(process.errorStream)
            onOutStream(process.inputStream)
        } finally {
            process?.waitFor()
            process?.destroy()
        }
    }

    fun execCmd(commands: Array<String>, isRooted: Boolean = true, checkError: Boolean = false): String {
        val outputStream = ByteArrayOutputStream()
        execCmd(commands, isRooted, onOutStream = {
            it.use { inStream ->
                val buffer = ByteArray(1024)
                var len = 0
                outputStream.reset()
                while (inStream.read(buffer).apply { len = this } > 0) {
                    outputStream.write(buffer, 0 ,len)
                }
            }
        }, onErrorStream = {
            it.use { inStream ->
                val buffer = ByteArray(1024)
                var len = 0
                outputStream.reset()
                while (inStream.read(buffer).apply { len = this } > 0) {
                    outputStream.write(buffer, 0 ,len)
                }
            }
            if (checkError && outputStream.size() > 0) {
                throw IOException(outputStream.toString())
            }
        })
        return outputStream.toString()
    }

    fun runCommand(command: String): String {
        return execCmd(arrayOf(command))
    }

    fun readTextFile(path: String): String {
        return execCmd(arrayOf("cat $path"))
    }

    fun writeTextFile(path: String, context: String) {
        execCmd(arrayOf("echo -n -e $context > $path"))
    }
}
